#include "kkgui_menu.h"

#include "kkgui_base.h"
#include "kkgui_app.h"

/* =============================== */
/* define */
#define MAX_DEEP    20

#define ANIM_START    1
#define ANIM_END      0

/* =============================== */
/* typedef */
typedef enum
{
    ENTER_LIST_LOAD,        // 进入子菜单
    BACK_LIST_LOAD,         // 返回父菜单 
    ENTER_LIST_FROM_APP,    // 进入子菜单
    BACK_LIST_FROM_APP,     // 返回父菜单 
}kkui_menu_acd_e;

typedef enum
{
    APP_IDLE,       // 
    APP_BACK,       // 返回父菜单 
    APP_ENTER,      // 进入子菜单
}kkui_menuapp_state_e;

typedef enum
{
    MSTATE_SYS_HOME,           // HOME页面
    MSTATE_LIST_OPEN,          // 列表切入页面
    MSTATE_LIST_SWITCHING,     // 列表选择页面
    MSTATE_ICON_OPEN,          // 图标切入页面
    MSTATE_ICON_SWITCHING,     // 图标选择页面
    MSTATE_CUTOUT_ANIM,        // 切出动画
    MSTATE_ENTER_VALUESET_LOOP,// 进入数值设置程序运行
    MSTATE_VALUESET_LOOP,      // 数值设置程序运行页面
    MSTATE_ENTER_APP_LOOP,     // 进入APP程序运行
    MSTATE_APP_LOOP,           // APP程序运行页面
    MSTATE_ENTER_APP_LOOP_WITH_LIST,     // 进入APP程序运行
    MSTATE_APP_LOOP_WITH_LIST,           // APP程序运行页面
}kkui_menu_state_e;

typedef struct
{
    uint8_t menu_id;                // 菜单ID
    uint8_t cursor_pos;             // 光标编号位置
    int cursor_dis;                 // 光标显示位置
    int list_shift_dis;             // 列表偏置位置
}kkui_menustre_proc_s; // 菜单过程参数

typedef struct
{
    uint8_t menu_id; 
    kkui_menu_type_e menu_type;     // 当前列表显示类型
    uint8_t tab_num;                // 标签数量
    kkui_menutab_info_s* member;    // 标签成员

    uint8_t layer;                 // 菜单层级
    uint8_t cursor_pos;             // 光标编号位置
    uint8_t l_cursor_pos;
    float cursor_dis;                 // 光标显示位置
    float cursor_width;               // 光标显示宽度
    int list_shift_dis;             // 列表偏置位置
    kkui_menustre_proc_s layer_info[MAX_DEEP];   // 菜单各层信息

    kkui_menuapp_state_e app_state;
    
    kkui_menu_state_e menu_state;   // 菜单状态
    uint8_t cut_out_state;          // 切出标志
}kkui_menu_proc_s; // 菜单过程参数

/* =============================== */
/* variable statement*/


/* =============================== */
/* variable definition*/
extern kkui_key_info_s key_list[MAX_KEY_NUM];

static kkui_menu_info_s* _uiMenuInfo;
static kkui_menu_proc_s _uiProc_s; 

/* =============================== */
/* function statement*/



/* =============================== */
/* function definition*/

void uiBackAppLoop(void)
{
    _uiProc_s.app_state = APP_BACK;
}

void uiEnterAppSubList(uint8_t sub_list_id)
{
    _uiProc_s.cursor_pos = sub_list_id; 
    _uiProc_s.app_state = APP_ENTER;
}


static float uiCalcOfVariation(float now_value, float target_value, float speed)
{
    if (fabs(target_value - now_value) < 0.2)
        return target_value;
    if (target_value != now_value)
        return (now_value + (target_value - now_value) * speed);
    return now_value;
}

static void uiMenuExitAnimation(float disapp_speec) // 渐变消失函数
{
    static float exit_anim_frame = 0;

    exit_anim_frame += disapp_speec;

    if(exit_anim_frame < 1)
        uiDisMask4Point(0, 0, DIS_WIDE, DIS_HIGH, 0x01, 0);
    else if(exit_anim_frame < 2)
        uiDisMask4Point(0, 0, DIS_WIDE, DIS_HIGH, 0x09, 0);
    else if(exit_anim_frame < 3)
        uiDisMask4Point(0, 0, DIS_WIDE, DIS_HIGH, 0x0a, 0);
    else if(exit_anim_frame < 4)
        uiDisMask4Point(0, 0, DIS_WIDE, DIS_HIGH, 0x0f, 0);

    if(exit_anim_frame >= 4)
    {
        _uiProc_s.cut_out_state = 0;
        exit_anim_frame = 0;
    }
}

// 图标模式菜单相关函数
static void uiGetMenuIconCurDis(float speed) // 计算列表状态下，光标位置，光标宽度，列表偏移
{   
    _uiProc_s.cursor_dis = uiCalcOfVariation(_uiProc_s.cursor_dis, _uiProc_s.cursor_pos * 60, speed);
}

static void uiMenuIconOpen(float open_speed)
{
    static float icon_open_pos = 0;
    static float name_dis = 0;
    uiDisClear(0);
    uiGetMenuIconCurDis(0.2);

    icon_open_pos = uiCalcOfVariation(icon_open_pos, 60, 0.15);
    
    for(int ret = 0; ret < _uiProc_s.tab_num; ret ++)
    {
        uiShowPicture((DIS_WIDE - MENU_MENU_ICON_SIZE)/2 + icon_open_pos * ret - _uiProc_s.cursor_dis - 60 + icon_open_pos, 10, MENU_MENU_ICON_SIZE, MENU_MENU_ICON_SIZE, (uint8_t*)_uiProc_s.member[ret].other_dis, 1);
    }
    if(_uiProc_s.l_cursor_pos != _uiProc_s.cursor_pos)
    {
        name_dis = 0;
        _uiProc_s.l_cursor_pos = _uiProc_s.cursor_pos;
    }
    name_dis = uiCalcOfVariation(name_dis, MENU_MENU_CURSOR_SIZE, 0.12);
    
    uiSetDisWindows(DIS_WIDE / 2 - (strlen(_uiProc_s.member[_uiProc_s.cursor_pos].name) * MENU_MENU_FONT_WIDTH / 2), DIS_HIGH - MENU_MENU_CURSOR_SIZE, strlen(_uiProc_s.member[_uiProc_s.cursor_pos].name) * MENU_MENU_FONT_WIDTH, MENU_MENU_FONT_HIGH);
    uiShowString(DIS_WIDE / 2 - (strlen(_uiProc_s.member[_uiProc_s.cursor_pos].name) * MENU_MENU_FONT_WIDTH / 2), DIS_HIGH - name_dis, (char*)_uiProc_s.member[_uiProc_s.cursor_pos].name, MENU_MENU_FONT_HIGH, 1);
    uiClearDisWindows();
    
    if(icon_open_pos >= 60)  // 退出加载状态
    {
        icon_open_pos = 0;
        _uiProc_s.menu_state = MSTATE_ICON_SWITCHING;
    }
}

static void uiMenuIconLoop(void)
{
    static float name_dis = MENU_MENU_CURSOR_SIZE;

    uiDisClear(0);
    uiGetMenuIconCurDis(0.2);

    for(int ret = 0; ret < _uiProc_s.tab_num; ret ++)
    {
        uiShowPicture((DIS_WIDE - MENU_MENU_ICON_SIZE)/2 + 60 * ret - _uiProc_s.cursor_dis, 10, MENU_MENU_ICON_SIZE, MENU_MENU_ICON_SIZE, (uint8_t*)_uiProc_s.member[ret].other_dis, 1);
    }
    if(_uiProc_s.l_cursor_pos != _uiProc_s.cursor_pos)
    {
        name_dis = 0;
        _uiProc_s.l_cursor_pos = _uiProc_s.cursor_pos;
    }
    name_dis = uiCalcOfVariation(name_dis, MENU_MENU_CURSOR_SIZE, 0.12);
    
    uiSetDisWindows(DIS_WIDE / 2 - (strlen(_uiProc_s.member[_uiProc_s.cursor_pos].name) * MENU_MENU_FONT_WIDTH / 2), DIS_HIGH - MENU_MENU_CURSOR_SIZE, strlen(_uiProc_s.member[_uiProc_s.cursor_pos].name) * MENU_MENU_FONT_WIDTH, MENU_MENU_FONT_HIGH);
    uiShowString(DIS_WIDE / 2 - (strlen(_uiProc_s.member[_uiProc_s.cursor_pos].name) * MENU_MENU_FONT_WIDTH / 2), DIS_HIGH - name_dis, (char*)_uiProc_s.member[_uiProc_s.cursor_pos].name, MENU_MENU_FONT_HIGH, 1);
    uiClearDisWindows();
}

// 列表模式菜单相关函数
static void uiGetMenuListCurDis(float speed_high, float speed_width) // 计算列表状态下，光标位置，光标宽度，列表偏移
{
    int targ_high = _uiProc_s.cursor_pos * MENU_MENU_CURSOR_SIZE;
    int targ_width = strlen(_uiProc_s.member[_uiProc_s.cursor_pos].name) * MENU_MENU_FONT_WIDTH + MENU_MENU_BOTHSIDE_SHIFT * 2;
    
    // 二阶动态系统
    // static float pid_high = 0,pid_err,pid_lerr; 
    // static float out_pid = 0;
    // static float high_out = 0;

    // static float pid2_high = 0,pid2_err,pid2_lerr,pid2_serr; 
    // static float out2_pid = 0;
    // static float high2_out = 0;

    // pid_high = high_out;
    // pid_err = targ_high - pid_high;
    // out_pid = 0.1 * pid_err - 0.16 * (pid_err - pid_lerr);
    // pid_lerr = pid_err;
    // if(pid_err > 3) pid_err = 3;
    // if(pid_err < -3) pid_err = -3;

    // high_out += out_pid;

    // pid2_high = high2_out;
    // pid2_err = high_out - pid2_high;
    // out2_pid = 0.1 * pid2_err - 0.17 * (pid2_err - pid2_lerr) + 0.008 * pid2_serr;
    // pid2_lerr = pid2_err;
    // pid2_serr += pid2_lerr;
    // if(pid2_err > 3) pid2_err = 3;
    // if(pid2_err < -3) pid2_err = -3;

    // high2_out += out2_pid;
    // _uiProc_s.cursor_dis = high2_out + 0.01;

    // // KKgui_log("PID OUT : %.2f, %d\r\n", high2_out, _uiProc_s.cursor_dis);

    // 阶梯线性比例动画
    
    _uiProc_s.cursor_dis = uiCalcOfVariation(_uiProc_s.cursor_dis, targ_high, speed_high);

    // 计算列表偏移量
    if((int)_uiProc_s.cursor_dis - _uiProc_s.list_shift_dis < 0)
    {
        _uiProc_s.list_shift_dis = _uiProc_s.cursor_dis;
    }
    if((int)_uiProc_s.cursor_dis - _uiProc_s.list_shift_dis > DIS_HIGH - MENU_MENU_CURSOR_SIZE)
    {
        _uiProc_s.list_shift_dis = _uiProc_s.cursor_dis - DIS_HIGH + MENU_MENU_CURSOR_SIZE;
    }

    // 光标宽度计算
    _uiProc_s.cursor_width = uiCalcOfVariation(_uiProc_s.cursor_width, targ_width, speed_width);
}

static void uiMenuListOpen(float open_speed)
{
    static float open_list_high = 0;
    // uint8_t open_list_high_dis = (open_list_high + 0.01);

    uiDisClear(0);
    uiGetMenuListCurDis(MENU_LIST_HIGH_PROP_SPEED, MENU_LIST_WIDTH_PROP_SPEED);

    for(int ret = 0; ret < _uiProc_s.tab_num; ret ++)
    {
        uiShowString(MENU_MENU_BOTHSIDE_SHIFT, MENU_MENU_CURSOR_SHIFT + ret * open_list_high - _uiProc_s.list_shift_dis - MENU_MENU_CURSOR_SIZE + open_list_high, (char*)_uiProc_s.member[ret].name, MENU_MENU_FONT_HIGH, 1);

        if(_uiProc_s.member[ret].type == VALUE_SETTINGS || (_uiProc_s.member[ret].other_dis != NULL && _uiProc_s.member[ret].type != SINGLE_CHOICE))
        {
            uiShowString(DIS_WIDE - 3 - 5 - MENU_MENU_FONT_WIDTH * strlen((char*)_uiProc_s.member[ret].other_dis), MENU_MENU_CURSOR_SHIFT + ret * open_list_high - _uiProc_s.list_shift_dis - MENU_MENU_CURSOR_SIZE + open_list_high, (char*)_uiProc_s.member[ret].other_dis , MENU_MENU_FONT_HIGH, 1);
        }
        
        if(_uiProc_s.member[ret].type == SINGLE_CHOICE)
        {
            uiDrawBox(DIS_WIDE - 3 - 3 - MENU_MENU_FONT_HIGH, MENU_MENU_CURSOR_SHIFT + ret * open_list_high - _uiProc_s.list_shift_dis - MENU_MENU_CURSOR_SIZE + open_list_high, MENU_MENU_FONT_HIGH, MENU_MENU_FONT_HIGH, 1);
            if(_uiProc_s.member[ret].param && *(bool*)_uiProc_s.member[ret].param)
                uiDrawBlock(DIS_WIDE - 3 - 3 - MENU_MENU_FONT_HIGH + 2, MENU_MENU_CURSOR_SHIFT + ret * open_list_high - _uiProc_s.list_shift_dis - MENU_MENU_CURSOR_SIZE + open_list_high + 2, MENU_MENU_FONT_HIGH - 4, MENU_MENU_FONT_HIGH - 4, 1);
        }

        uiDrawHLine(DIS_WIDE - 3, ret * ((float)DIS_HIGH / _uiProc_s.tab_num), 3, 1);
    }
    uiDrawHLine(DIS_WIDE - 3, DIS_HIGH - 1, 3, 1);
    uiDrawVLine(DIS_WIDE - 2, 0, DIS_HIGH, 1);
    uiDrawBlock(DIS_WIDE - 3, DIS_HIGH * _uiProc_s.cursor_dis / (_uiProc_s.tab_num * MENU_MENU_CURSOR_SIZE) + 1, 3, ((float)DIS_HIGH / _uiProc_s.tab_num) - 0.01, 1);

    uiDrawRBlock(0, _uiProc_s.cursor_dis - _uiProc_s.list_shift_dis, _uiProc_s.cursor_width ,MENU_MENU_CURSOR_SIZE, 5, 2);

    open_list_high = uiCalcOfVariation(open_list_high, MENU_MENU_CURSOR_SIZE, open_speed);

    if(open_list_high + 0.01 >= MENU_MENU_CURSOR_SIZE) // 退出加载状态
    {
        open_list_high = 0;
        _uiProc_s.menu_state = MSTATE_LIST_SWITCHING;
    }
}

static void uiMenuListLoop(void)
{
    uiDisClear(0);
    uiGetMenuListCurDis(MENU_LIST_HIGH_PROP_SPEED, MENU_LIST_WIDTH_PROP_SPEED);

    for(int ret = 0; ret < _uiProc_s.tab_num; ret ++)
    {
        uiShowString(MENU_MENU_BOTHSIDE_SHIFT, MENU_MENU_CURSOR_SHIFT + ret * MENU_MENU_CURSOR_SIZE - _uiProc_s.list_shift_dis, (char*)_uiProc_s.member[ret].name , MENU_MENU_FONT_HIGH, 1);
        if(_uiProc_s.member[ret].type == VALUE_SETTINGS || (_uiProc_s.member[ret].other_dis != NULL && _uiProc_s.member[ret].type != SINGLE_CHOICE))
        {
            uiShowString(DIS_WIDE - 3 - 5 - MENU_MENU_FONT_WIDTH * strlen((char*)_uiProc_s.member[ret].other_dis), MENU_MENU_CURSOR_SHIFT + ret * MENU_MENU_CURSOR_SIZE - _uiProc_s.list_shift_dis, (char*)_uiProc_s.member[ret].other_dis , MENU_MENU_FONT_HIGH, 1);
        }

        if(_uiProc_s.member[ret].type == SINGLE_CHOICE)
        {
            uiDrawBox(DIS_WIDE - 3 - 3 - MENU_MENU_FONT_HIGH, MENU_MENU_CURSOR_SHIFT + ret * MENU_MENU_CURSOR_SIZE - _uiProc_s.list_shift_dis, MENU_MENU_FONT_HIGH, MENU_MENU_FONT_HIGH, 1);
            if(_uiProc_s.member[ret].param && *(bool*)_uiProc_s.member[ret].param)
                uiDrawBlock(DIS_WIDE - 3 - 3 - MENU_MENU_FONT_HIGH + 2, MENU_MENU_CURSOR_SHIFT + ret * MENU_MENU_CURSOR_SIZE - _uiProc_s.list_shift_dis + 2, MENU_MENU_FONT_HIGH - 4, MENU_MENU_FONT_HIGH - 4, 1);
        }
        uiDrawHLine(DIS_WIDE - 3, ret * ((float)DIS_HIGH / _uiProc_s.tab_num), 3, 1);
    }
    uiDrawHLine(DIS_WIDE - 3, DIS_HIGH - 1, 3, 1);
    uiDrawVLine(DIS_WIDE - 2, 0, DIS_HIGH, 1);
    uiDrawBlock(DIS_WIDE - 3, DIS_HIGH * _uiProc_s.cursor_dis / (_uiProc_s.tab_num * MENU_MENU_CURSOR_SIZE) + 1, 3, ((float)DIS_HIGH / _uiProc_s.tab_num) - 0.01, 1);

		if(_uiProc_s.menu_state == MSTATE_VALUESET_LOOP)
				uiDrawRBlock(DIS_WIDE - 3 - 7 - MENU_MENU_FONT_WIDTH * strlen((char*)_uiProc_s.member[_uiProc_s.cursor_pos].other_dis), MENU_MENU_CURSOR_SHIFT + _uiProc_s.cursor_pos * MENU_MENU_CURSOR_SIZE - _uiProc_s.list_shift_dis - MENU_MENU_CURSOR_SHIFT, MENU_MENU_FONT_WIDTH * strlen((char*)_uiProc_s.member[_uiProc_s.cursor_pos].other_dis) + 4, MENU_MENU_CURSOR_SIZE, 5, 2);
		
    uiDrawRBlock(0, _uiProc_s.cursor_dis - _uiProc_s.list_shift_dis, _uiProc_s.cursor_width ,MENU_MENU_CURSOR_SIZE, 5, 2);
}


// 菜单层级切换数据重载与保存
void uiMenuProcLoad(uint8_t load_type)
{    
    uint8_t load_id;
    if(load_type == ENTER_LIST_LOAD)
    {
        load_id = _uiProc_s.member[_uiProc_s.cursor_pos].sub_menu_id;       // 载入子级菜单ID

        _uiProc_s.layer_info[_uiProc_s.layer].cursor_pos = _uiProc_s.cursor_pos;            // 保存当前级光标编号
        _uiProc_s.layer_info[_uiProc_s.layer].menu_id = _uiProc_s.menu_id;                  // 保存当前级ID
        _uiProc_s.layer_info[_uiProc_s.layer].cursor_dis = _uiProc_s.cursor_dis;            // 保存当前级光标显示位置
        _uiProc_s.layer_info[_uiProc_s.layer].list_shift_dis = _uiProc_s.list_shift_dis;    // 保存当前级列表偏移显示位置

        _uiProc_s.layer ++;

        // 载入当前ID菜单显示信息
        _uiProc_s.cursor_pos = 0;    // 载入光标编号
        _uiProc_s.list_shift_dis = 0;    // 载入列表偏移显示位置
        _uiProc_s.cursor_dis = 0;    // 载入光标显示位置
        _uiProc_s.cursor_width = 0;               // 光标显示宽度
        _uiProc_s.l_cursor_pos = KKUI_NONE;

        // 载入当前ID菜单信息
        _uiProc_s.menu_id = load_id; 
        _uiProc_s.tab_num = _uiMenuInfo[load_id].tab_num;
        _uiProc_s.member = _uiMenuInfo[load_id].member;
        _uiProc_s.menu_type = _uiMenuInfo[load_id].menu_type;
    } 
    else if(load_type == BACK_LIST_LOAD)
    {
        _uiProc_s.layer --;
        load_id = _uiProc_s.layer_info[_uiProc_s.layer].menu_id;               // 恢复父级ID，父级历史信息已保存至_uiProc_s.layer_info

        // 载入当前ID菜单显示信息
        _uiProc_s.cursor_pos = _uiProc_s.layer_info[_uiProc_s.layer].cursor_pos;    // 载入光标编号
        _uiProc_s.list_shift_dis = _uiProc_s.layer_info[_uiProc_s.layer].list_shift_dis;    // 载入列表偏移显示位置
        _uiProc_s.cursor_dis = _uiProc_s.layer_info[_uiProc_s.layer].cursor_dis;    // 载入光标显示位置
        _uiProc_s.cursor_width = 0;               // 光标显示宽度
        _uiProc_s.l_cursor_pos = KKUI_NONE;

        // 载入当前ID菜单信息
        _uiProc_s.menu_id = load_id; 
        _uiProc_s.tab_num = _uiMenuInfo[load_id].tab_num;
        _uiProc_s.member = _uiMenuInfo[load_id].member;
        _uiProc_s.menu_type = _uiMenuInfo[load_id].menu_type;
    }

    if(_uiProc_s.menu_type == LIST_STRING)
    {
        _uiProc_s.menu_state = MSTATE_LIST_OPEN;
    }
    else if(_uiProc_s.menu_type == LIST_ICON)
    {
        _uiProc_s.menu_state = MSTATE_ICON_OPEN;
    }
    else if(_uiProc_s.menu_type == LIST_HOME)
    {
        _uiProc_s.menu_state = MSTATE_SYS_HOME;
    }
    else if(_uiProc_s.menu_type == LIST_WITH_LOOP)
    {
        _uiProc_s.menu_state = MSTATE_ENTER_APP_LOOP_WITH_LIST;
    }
}

// 输入操作判断与动作
void uiJudgStatus(void)
{
    switch(_uiProc_s.menu_state)
    {
        case MSTATE_SYS_HOME:
        {
            if(MENU_KEY_ENTER)
            {
                uiMenuProcLoad(ENTER_LIST_LOAD);
                _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
            }
            break;
        }
        case MSTATE_ICON_OPEN:
        case MSTATE_ICON_SWITCHING:
        case MSTATE_LIST_OPEN:
        case MSTATE_LIST_SWITCHING:
        {
            if(MENU_KEY_BACK || _uiProc_s.app_state == APP_BACK)
            {
                if(_uiProc_s.layer > 0)
                    uiMenuProcLoad(BACK_LIST_LOAD); // back 后菜单层级数据以重载，所以menu_func(BACK_LIST,...)执行的是退出的那一层的
                if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL) // 后执行函数，LOAD后会改变
                    _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(BACK_LIST, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param); 
                _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
            }
            if(MENU_KEY_ENTER)
            {
                if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ENTER_LIST) // 子级为列表
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL) // 先执行函数，LOAD后会改变数据
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                    uiMenuProcLoad(ENTER_LIST_LOAD); // 需完善状态切换，切入切出动画逻辑
                    _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                }
                else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == SINGLE_CHOICE) // 单选功能
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].param) // 判断指针非空
                        *(bool*)_uiProc_s.member[_uiProc_s.cursor_pos].param = !(*(bool*)_uiProc_s.member[_uiProc_s.cursor_pos].param);
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                }
                else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == VALUE_SETTINGS) // 子级为数值设置
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                    {
                        // _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param); //  
                        _uiProc_s.menu_state = MSTATE_ENTER_VALUESET_LOOP;
                    }
                }
                else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ACTION_EXE_ONCE) // 子级为单次执行
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                }
                else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == GO_BACK_LIST) // 子级为单次执行
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                    if(_uiProc_s.layer > 0)
                        uiMenuProcLoad(BACK_LIST_LOAD); // back 后菜单层级数据以重载，所以menu_func(BACK_LIST,...)执行的是退出的那一层的
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL) // 后执行函数，LOAD后会改变
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(BACK_LIST, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param); 
                    _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                }
                else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ACTION_EXE_LOOP) // 子级为循环执行
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                    {
                        _uiProc_s.menu_state = MSTATE_ENTER_APP_LOOP;
                        _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                    }
                }
                else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ACTION_EXE_LOOP_WITH_LIST) // 子级为循环执行且带菜单功能
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                    {
                        uiMenuProcLoad(ENTER_LIST_LOAD); // 需完善状态切换，切入切出动画逻辑
                        _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                    }
                }
            }
            if(_uiProc_s.menu_state == MSTATE_LIST_OPEN || _uiProc_s.menu_state == MSTATE_LIST_SWITCHING)
            {
                if(MENU_KEY_DOWN)
                {
                    if(_uiProc_s.cursor_pos<_uiProc_s.tab_num - 1)
                    {
                        _uiProc_s.cursor_pos++;
                    }
                    else
                    {
                        _uiProc_s.cursor_pos = 0;
                    }
                }
                if(MENU_KEY_UP)
                {
                    if(_uiProc_s.cursor_pos>0)
                    {
                        _uiProc_s.cursor_pos--;
                    }
                    else
                    {
                        _uiProc_s.cursor_pos = _uiProc_s.tab_num - 1;
                    }
                }
            }
            if(_uiProc_s.menu_state == MSTATE_ICON_OPEN || _uiProc_s.menu_state == MSTATE_ICON_SWITCHING)
            {
                if(MENU_KEY_REGHT)
                {
                    if(_uiProc_s.cursor_pos<_uiProc_s.tab_num - 1)
                    {
                        _uiProc_s.cursor_pos++;
                    }
                    else
                    {
                        _uiProc_s.cursor_pos = 0;
                    }
                }
                if(MENU_KEY_LETF)
                {
                    if(_uiProc_s.cursor_pos>0)
                    {
                        _uiProc_s.cursor_pos--;
                    }
                    else
                    {
                        _uiProc_s.cursor_pos = _uiProc_s.tab_num - 1;
                    }
                }
            }
            break;
        }
        case MSTATE_APP_LOOP_WITH_LIST:
        {            
            if(_uiProc_s.app_state == APP_BACK)
            {
                if(_uiProc_s.layer > 0)
                    uiMenuProcLoad(BACK_LIST_LOAD);
                if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL) // 后执行函数，LOAD后会改变
                    _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(BACK_LIST, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param); 
                _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
            }
            else if(_uiProc_s.app_state == APP_ENTER)
            {
                if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ENTER_LIST) // 子级为列表
                {
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL) // 先执行函数，LOAD后会改变数据
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                    uiMenuProcLoad(ENTER_LIST_LOAD); // 需完善状态切换，切入切出动画逻辑
                    _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                }
                // else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ACTION_EXE_ONCE) // 子级为单次执行
                // {
                //     if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                //         _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                // }
                // else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ACTION_EXE_LOOP) // 子级为循环执行
                // {
                //     if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                //     {
                //         _uiProc_s.menu_state = MSTATE_ENTER_APP_LOOP;
                //         _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                //     }
                // }
                // else if(_uiProc_s.member[_uiProc_s.cursor_pos].type == ACTION_EXE_LOOP_WITH_LIST) // 子级为循环执行且带菜单功能
                // {
                //     if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func != NULL)
                //     {
                //         uiMenuProcLoad(ENTER_LIST_LOAD); // 需完善状态切换，切入切出动画逻辑
                //         _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                //     }
                // }
            }
            break;
        }
        case MSTATE_APP_LOOP:
        {
            if(_uiProc_s.app_state == APP_BACK)
            {
                if(_uiProc_s.menu_type == LIST_STRING)
                {
                    _uiProc_s.menu_state = MSTATE_LIST_OPEN;
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func)
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(BACK_LIST, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                    _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                }
                else if(_uiProc_s.menu_type == LIST_ICON)
                {
                    _uiProc_s.menu_state = MSTATE_ICON_OPEN;
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func)
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(BACK_LIST, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                    _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                }
                else if(_uiProc_s.menu_type == LIST_HOME)
                {
                    _uiProc_s.menu_state = MSTATE_SYS_HOME;
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func)
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(BACK_LIST, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                    _uiProc_s.cut_out_state = 1;            // 菜单界面切换，设置切出动画标志位
                }
            }
            break;
        }
        case MSTATE_VALUESET_LOOP:
        {
            if(_uiProc_s.app_state == APP_BACK)
            {
                if(_uiProc_s.menu_type == LIST_STRING)
                {
                    _uiProc_s.menu_state = MSTATE_LIST_SWITCHING;
                    if(_uiProc_s.member[_uiProc_s.cursor_pos].menu_func)
                        _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(BACK_LIST, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
                }
            }
            break;
        }
    }
    _uiProc_s.app_state = APP_IDLE;
}


// 初始化首次启动参数
void uiMenuInit(kkui_menu_info_s* uiMenuInfo)
{
    uint8_t init_id = MENU_INIT_INTER;

    _uiMenuInfo = uiMenuInfo;

    _uiProc_s.menu_id = init_id;                // 初始菜单ID
    _uiProc_s.menu_type = _uiMenuInfo[init_id].menu_type;   // 当前列表显示类型
    _uiProc_s.tab_num = _uiMenuInfo[init_id].tab_num;   // 成员数量
    _uiProc_s.member = _uiMenuInfo[init_id].member;     // 成员信息
    _uiProc_s.layer = MENU_INIT_INTER;          // 初始化层级
    _uiProc_s.layer_info[_uiProc_s.layer].cursor_pos = 0;   // 层级光标列表位置
    _uiProc_s.cursor_pos = 0;                   // 光标列表位置
    _uiProc_s.l_cursor_pos = KKUI_NONE;
    _uiProc_s.cursor_dis = 0;                   // 光标显示位置
    _uiProc_s.list_shift_dis = 0;               // 光标列表偏移位置
    _uiProc_s.cursor_width = 0;                 // 光标显示宽度
    _uiProc_s.app_state = APP_IDLE;                    // APP运行状态
    _uiProc_s.menu_state = MSTATE_SYS_HOME;            // 首页状态
    _uiProc_s.cut_out_state = 0;
}

// 菜单循环
void uiMenuLoop(void)
{
    uiJudgStatus();

    if(_uiProc_s.cut_out_state) // 渐变消失，因为单独作为一个状态判断子状态比较复杂，所以独立为一个动作
    {
        uiMenuExitAnimation(PAGE_DISAPP_SPEED);
        return;
    }

    switch(_uiProc_s.menu_state) // 菜单状态
    {
        case MSTATE_SYS_HOME:
        {
            _uiProc_s.member[0].menu_func(LOOP_RUN, _uiProc_s.member[0].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
            break;
        }

        case MSTATE_ICON_OPEN:
        {
            uiMenuIconOpen(MENU_LIST_OPEN_PROP_SPEED);
            break;
        }
        case MSTATE_ICON_SWITCHING:
        {
            uiMenuIconLoop();
            break;
        }

        case MSTATE_LIST_OPEN:
        {
            uiMenuListOpen(MENU_LIST_OPEN_PROP_SPEED);
            break;
        }

        case MSTATE_LIST_SWITCHING:
        {
            uiMenuListLoop();
            break;
        }

        case MSTATE_ENTER_VALUESET_LOOP:
        {
            _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param); //  去掉enter状态，无意义
            _uiProc_s.menu_state = MSTATE_VALUESET_LOOP;  // 单次执行后进入LOOP
            break;
        }

        case MSTATE_VALUESET_LOOP:
        {
            _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(LOOP_RUN, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
            uiMenuListLoop();
            break;
        }

        case MSTATE_ENTER_APP_LOOP_WITH_LIST: // ENTER 状态是为了更好的处理进入event执行函数和消失动画之间的冲突
        {
            _uiMenuInfo[_uiProc_s.layer_info[_uiProc_s.layer - 1].menu_id].member[_uiProc_s.layer_info[_uiProc_s.layer - 1].cursor_pos].menu_func(ENTER_TAG, _uiMenuInfo[_uiProc_s.layer_info[_uiProc_s.layer - 1].menu_id].member[_uiProc_s.layer_info[_uiProc_s.layer - 1].cursor_pos].name, _uiMenuInfo[_uiProc_s.layer_info[_uiProc_s.layer - 1].menu_id].member[_uiProc_s.layer_info[_uiProc_s.layer - 1].cursor_pos].param);
            _uiProc_s.menu_state = MSTATE_APP_LOOP_WITH_LIST;   // 次执行后进入LOOP
            break;
        }

        case MSTATE_APP_LOOP_WITH_LIST:
        {
            _uiMenuInfo[_uiProc_s.layer_info[_uiProc_s.layer - 1].menu_id].member[_uiProc_s.layer_info[_uiProc_s.layer - 1].cursor_pos].menu_func(LOOP_RUN, _uiMenuInfo[_uiProc_s.layer_info[_uiProc_s.layer - 1].menu_id].member[_uiProc_s.layer_info[_uiProc_s.layer - 1].cursor_pos].name, _uiMenuInfo[_uiProc_s.layer_info[_uiProc_s.layer - 1].menu_id].member[_uiProc_s.layer_info[_uiProc_s.layer - 1].cursor_pos].param);
            break;
        }

        case MSTATE_ENTER_APP_LOOP:
        {
            _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(ENTER_TAG, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
            _uiProc_s.menu_state = MSTATE_APP_LOOP;  // 单次执行后进入LOOP
            break;
        }

        case MSTATE_APP_LOOP:
        {
            _uiProc_s.member[_uiProc_s.cursor_pos].menu_func(LOOP_RUN, _uiProc_s.member[_uiProc_s.cursor_pos].name, _uiProc_s.member[_uiProc_s.cursor_pos].param);
            break;
        }
    }

}

